import { getMCPClient } from './mcp-client.js';
import { extractToolCallsFromText } from './lib/tool-call-utils.js';
import { createWebContentPreview } from './lib/chrome-web-content.js';
import { getToolDefinition, isToolAllowed } from './tools/registry.js';

const TOOL_CALL_DELAY_MS = 500;
const FOCUS_RETRY_MAX = 3;
const FOCUS_RETRY_DELAY_MS = 200;
const INTERACTIVE_QUERY_PROPERTIES = ['visible', 'disabled', 'aria-disabled'];

const delay = (ms) => new Promise(resolve => setTimeout(resolve, ms));

const isElementEditable = (element) => {
    if (!element || typeof element !== 'object') {
        return false;
    }

    const { disabled, visible, attributes = {} } = element;
    const ariaDisabled = attributes['aria-disabled'];
    const ariaHidden = attributes['aria-hidden'];

    if (disabled === true || disabled === 'true') {
        return false;
    }
    if (ariaDisabled === true || ariaDisabled === 'true') {
        return false;
    }
    if (ariaHidden === true || ariaHidden === 'true') {
        return false;
    }
    if (visible === false || visible === 'false') {
        return false;
    }
    return true;
};

const buildInteractiveQuery = (selector) => ({
    selector,
    includeAttributes: INTERACTIVE_QUERY_PROPERTIES,
    includeCoordinates: true,
    maxResults: 1
});

export class BaseAgent {
    constructor(llmClient = null, mcpConfig = null) {
        console.log("[BaseAgent] BaseAgent constructor", "llmClient: ", llmClient, "mcpConfig: ", mcpConfig);

        this.llmClient = llmClient;
        this.mcpClient = mcpConfig ? getMCPClient(mcpConfig) : null;
        this.toolsEnabled = false;
    }

    setLLM(llmClient) {
        this.llmClient = llmClient;
    }

    setMCP(mcpConfig) {
        this.mcpClient = getMCPClient(mcpConfig);
    }

    attachMCPClient(client) {
        this.mcpClient = client;
        this.toolsEnabled = Boolean(client);
        if (this.toolsEnabled) {
            console.log('[BaseAgent] MCP 客户端已更新并启用');
        }
    }

    async enableTools() {
        if (this.mcpClient) {
            try {
                console.log('[BaseAgent] 开始初始化MCP工具...');
                await this.mcpClient.initialize();
                
                // 检查工具是否成功加载
                const toolsCount = this.mcpClient.getAvailableTools().length;
                if (toolsCount > 0) {
                    this.toolsEnabled = true;
                    console.log(`[BaseAgent] MCP 工具已启用，共 ${toolsCount} 个工具`);
                } else {
                    this.toolsEnabled = false;
                    console.warn('[BaseAgent] MCP 初始化成功但未找到工具');
                }
            } catch (error) {
                console.warn('[BaseAgent] MCP 工具启用失败:', error);
                this.toolsEnabled = false;
                // 重置MCP客户端状态
                if (this.mcpClient) {
                    this.mcpClient.initialized = false;
                }
            }
        } else {
            console.log('[BaseAgent] 没有MCP客户端，跳过工具启用');
            this.toolsEnabled = false;
        }
    }

    async *streamResponse(messages, options = {}) {
        if (!this.llmClient || typeof this.llmClient.streamChat !== 'function') {
            throw new Error('LLM 客户端未配置');
        }

        // 如果启用了工具，在系统消息中添加工具描述
        if (this.toolsEnabled && this.mcpClient) {
            const rawToolsPrompt = this.mcpClient.generateToolsPrompt();
            const promptString = typeof rawToolsPrompt === 'string' ? rawToolsPrompt : '';
            const toolsSection = promptString.trim() ? promptString : '当前没有可用的 MCP 工具。';
            const placeholder = '{MCP_TOOLS}';

            const systemMessageIndex = messages.findIndex((msg) => {
                if (msg.role !== 'system' || !msg.content) return false;
                if (typeof msg.content === 'string') {
                    return msg.content.includes(placeholder);
                }
                if (Array.isArray(msg.content)) {
                    return msg.content.some((part) => typeof part === 'string' && part.includes(placeholder));
                }
                return false;
            });

            if (systemMessageIndex !== -1) {
                const systemMessage = messages[systemMessageIndex];

                if (typeof systemMessage.content === 'string') {
                    systemMessage.content = systemMessage.content.split(placeholder).join(toolsSection);
                } else if (Array.isArray(systemMessage.content)) {
                    systemMessage.content = systemMessage.content.map((part) => {
                        if (typeof part !== 'string') {
                            return part;
                        }
                        return part.includes(placeholder)
                            ? part.split(placeholder).join(toolsSection)
                            : part;
                    });
                }
            } else {
                console.log('[BaseAgent] 未找到 {MCP_TOOLS} 占位符，跳过工具描述拼接');
            }
        } else {
            console.log('[BaseAgent] 工具未启用或MCP客户端不可用', {
                toolsEnabled: this.toolsEnabled,
                hasMCPClient: !!this.mcpClient
            });
        }

        console.log('[BaseAgent] 调用模型，消息内容:', JSON.stringify(messages));

        // 流式获取LLM响应
        for await (const chunk of this.llmClient.streamChat(messages, options)) {
            yield chunk;
        }
    }

    async processToolCalls(fullResponse, hooks = {}) {
        if (!this.toolsEnabled || !this.mcpClient) {
            return { toolCalls: [], toolResults: [], appendedText: '' };
        }

        const toolCalls = extractToolCallsFromText(fullResponse);
        if (!toolCalls.length) {
            return { toolCalls: [], toolResults: [], appendedText: '' };
        }

        console.log('[BaseAgent] 检测到工具调用:', toolCalls);

        const { onToolCall } = hooks || {};
        const toolResults = [];

        for (let index = 0; index < toolCalls.length; index += 1) {
            const toolCall = toolCalls[index];

            // action_id                :                1
            // executor_id                :                "chrome_navigate"
            // goal                :                "打开淘宝网站，为搜索iPhone 17做准备。"
            // inputs                :            {url: 'https://www.taobao.com'}

            // 新数据格式
            // {
            //     "tool": "chrome_navigate",
            //     "parameters": {
            //     "url": "https://www.taobao.com"
            // }
            // }
            const toolName = toolCall?.tool || toolCall?.tool_name;
            const toolArgs = toolCall?.parameters || toolCall?.arguments;
            const executorId = toolCall?.executor_id;

            if (executorId === "agent") {
                continue
            }

            if (!toolName) {
                console.warn('[BaseAgent] 忽略缺少 tool 标识的调用:', toolCall);
                continue;
            }

            if (!isToolAllowed(toolName)) {
                console.warn('[BaseAgent] 不是有效 tool', toolName, toolCall);
                continue;
            }

            let processedResult = null;
            let rawResult = null;
            let errorMessage = null;
            const startTime = Date.now();
            let activationLog = null;
            let suppressObservation = false;
            let skipDelay = false;
            const toolDefinition = getToolDefinition(toolName);
            const toolContext = {
                toolName,
                args: toolArgs,
                toolCall,
                mcpClient: this.mcpClient,
                baseAgent: this
            };

            const resolveFlag = async (flag, context, fallback = false) => {
                if (typeof flag === 'function') {
                    try {
                        return Boolean(await flag(context));
                    } catch (error) {
                        console.warn('[BaseAgent] 工具标志计算失败，使用回退值:', error);
                        return fallback;
                    }
                }
                if (flag === undefined || flag === null) {
                    return fallback;
                }
                return Boolean(flag);
            };

            try {
                if (typeof toolDefinition.beforeCall === 'function') {
                    activationLog = await toolDefinition.beforeCall(toolContext);
                }

                const callResult = await toolDefinition.doCall(toolContext);
                rawResult = toolDefinition.getToolRawResult
                    ? await toolDefinition.getToolRawResult(callResult, toolContext)
                    : callResult;

                processedResult = toolDefinition.getToolTextResult
                    ? await toolDefinition.getToolTextResult(rawResult, toolContext)
                    : rawResult;

                suppressObservation = await resolveFlag(toolDefinition.suppressObservation, {
                    ...toolContext,
                    rawResult,
                    processedResult
                });

                skipDelay = await resolveFlag(toolDefinition.skipDelay, {
                    ...toolContext,
                    rawResult,
                    processedResult
                });

                toolResults.push({
                    tool: toolName,
                    result: processedResult,
                    suppressObservation,
                    activationLog
                });
                console.log(`[BaseAgent] 工具 "${toolName}" 执行成功`, processedResult);
                if (toolName === 'chrome_get_web_content') {
                    console.log('[BaseAgent] chrome_get_web_content 返回内容预览:', createWebContentPreview(processedResult));
                }
            } catch (error) {
                errorMessage = error.message || String(error);
                console.error(`[BaseAgent] 工具 "${toolName}" 执行失败:`, error);
                suppressObservation = await resolveFlag(toolDefinition?.suppressObservation, {
                    ...toolContext,
                    rawResult,
                    processedResult,
                    error
                });
                skipDelay = await resolveFlag(toolDefinition?.skipDelay, toolContext);
                toolResults.push({
                    tool: toolName,
                    error: errorMessage,
                    suppressObservation
                });
            } finally {
                if (typeof onToolCall === 'function') {
                    try {
                        onToolCall({
                            index,
                            toolCall,
                            result: processedResult,
                            rawResult,
                            error: errorMessage,
                            durationMs: Date.now() - startTime,
                            suppressObservation
                        });
                    } catch (callbackError) {
                        console.warn('[BaseAgent] onToolCall 回调执行失败:', callbackError);
                    }
                }
            }

            if (!skipDelay) {
                await delay(TOOL_CALL_DELAY_MS);
            }
        }

        const visibleResults = toolResults.filter(item => !item.suppressObservation);
        const appendedText = visibleResults.length > 0
            ? `\n\n## 工具执行结果\n${this.formatToolResults(visibleResults)}`
            : '';

        return { toolCalls, toolResults, appendedText };
    }

    async ensureInputIsActive(selector) {
        const log = [];

        const queryInteractive = async () => {
            log.push(`🔍 检查输入框状态: ${selector}`);
            const response = await this.mcpClient.callTool('chrome_get_interactive_elements', buildInteractiveQuery(selector));
            const element = Array.isArray(response?.elements) ? response.elements[0] : response?.[0];
            return element;
        };

        const clickElement = async () => {
            log.push('🖱️ 尝试点击输入框以激活');
            await this.mcpClient.callTool('chrome_click_element', { selector, waitForNavigation: false });
        };

        for (let attempt = 1; attempt <= FOCUS_RETRY_MAX; attempt += 1) {
            const element = await queryInteractive();
            if (isElementEditable(element)) {
                log.push('✅ 输入框可编辑');
                return log.join('\n');
            }

            log.push(`⚠️ 输入框不可编辑（尝试 ${attempt}/${FOCUS_RETRY_MAX}）`);
            await clickElement();
            await delay(FOCUS_RETRY_DELAY_MS);
        }

        log.push('❌ 多次尝试后输入框仍不可编辑');
        return log.join('\n');
    }

    getText(baseText = '', toolProcessing = null) {
        const appendedText = toolProcessing?.appendedText || '';
        if (appendedText) {
            return `${baseText}${appendedText}`;
        }
        return baseText;
    }

    formatToolResults(toolResults) {
        let formatted = '';
        
        for (const result of toolResults) {
            const toolLabel = result.tool || result.tool_name || '未知工具';
            formatted += `### ${toolLabel}\n`;
            if (result.error) {
                formatted += `❌ 执行失败: ${result.error}\n\n`;
            } else {
                formatted += `✅ 执行成功\n`;
                if (result.result) {
                    formatted += `结果: ${JSON.stringify(result.result, null, 2)}\n\n`;
                }
            }
        }
        
        return formatted;
    }

    async getAvailableTools() {
        if (this.mcpClient) {
            await this.mcpClient.initialize();
            return this.mcpClient.getAvailableTools();
        }
        return [];
    }
}
